import $ from 'jquery';
import 'jquery-mousewheel';
import Hammer from 'hammerjs';

let gLastPanX = 0,
  gLastPanY = 0,
  gLastScale = 1.0;
let gLastMouseX = 0,
  gLastMouseY = 0,
  gMousePressedId = -1;
let gViewer,
  gViewport;

function attachEvents(elemId, castViewer) {
  const cast_viewport = $(`#${elemId}`);
  gViewer = castViewer, gViewport = cast_viewport[0];
  Init(gViewport);
  cast_viewport.mousedown((event) => {
    dispatch(event);
    event.preventDefault();
    return false;
  });
  cast_viewport.mouseup((event) => {
    dispatch(event);
    event.preventDefault();
    return false;
  });
  cast_viewport.mousemove((event) => {
    dispatch(event);
    event.preventDefault();
    return false;
  });
  cast_viewport.mousewheel((event) => {
    dispatch(event);
    event.preventDefault();
    return false;
  });
  cast_viewport.mouseout((event) => {
    gMousePressedId = -1;
    event.preventDefault();
    return false;
  });
  // events - mouse
  window.oncontextmenu = function (event) {
    event.preventDefault();
    event.stopPropagation();
    return false;
  };
}

function Init(viewport) {
  const hammertime = new Hammer.Manager(viewport);
  const singlepan = new Hammer.Pan({
    event: 'pan',
    direction: Hammer.DIRECTION_ALL,
    threshold: 5,
    pointers: 1,
  });
  const multipan = new Hammer.Pan({
    event: 'multipan',
    direction: Hammer.DIRECTION_ALL,
    threshold: 5,
    pointers: 2,
  });
  const pinch = new Hammer.Pinch();
  hammertime.add(pinch);
  hammertime.add(singlepan);
  hammertime.add(multipan);

  pinch.recognizeWith(multipan);
  singlepan.recognizeWith(multipan);

  hammertime.on('pan', OnPan);
  hammertime.on('panstart', OnPanStart);
  hammertime.on('multipan', OnMultiPan);
  hammertime.on('multipanstart', OnMultiPanStart);
  hammertime.on('pinch', OnPinch);
  hammertime.on('pinchstart', OnPinchStart);

  // events
  window.addEventListener('resize', OnCastViewportResize, false);
}

function dispatch(event) {
  if (event.type == 'mousemove') {
    if (gMousePressedId == -1) { return; }
    const offsetX = event.clientX - gLastMouseX;
    const offsetY = event.clientY - gLastMouseY;
    gLastMouseX = event.clientX;
    gLastMouseY = event.clientY;
    if (gMousePressedId == 0) {
      gViewer.RotateModel(offsetX, offsetY);
    } else if (gMousePressedId == 1 || gMousePressedId == 2) {
      gViewer.MoveModel(offsetX, offsetY);
    }
  } else if (event.type == 'mousedown') {
    gLastMouseX = event.clientX;
    gLastMouseY = event.clientY;
    gMousePressedId = event.button;
  } else if (event.type == 'mouseup') {
    gMousePressedId = -1;
  } else if (event.type == 'mousewheel') {
    // event.deltaX, event.deltaY, event.deltaFactor
    if (event.deltaY > 0) { gViewer.ScaleModel(1.1); } else { gViewer.ScaleModel(0.9); }
  }
}

function OnPanStart(evt) {
  if (evt.pointerType == 'mouse') { return; }
  gLastPanX = evt.deltaX;
  gLastPanY = evt.deltaY;
}

function OnPan(evt) {
  if (evt.pointerType == 'mouse') { return; }
  let deltaX = evt.deltaX - gLastPanX,
    deltaY = evt.deltaY - gLastPanY;
  gLastPanX = evt.deltaX;
  gLastPanY = evt.deltaY;
  gViewer.RotateModel(deltaX, deltaY);
}

function OnMultiPanStart(evt) {
  if (evt.pointerType == 'mouse') { return; }
  gLastPanX = evt.deltaX;
  gLastPanY = evt.deltaY;
}

function OnMultiPan(evt) {
  if (evt.pointerType == 'mouse') { return; }
  let deltaX = evt.deltaX - gLastPanX,
    deltaY = evt.deltaY - gLastPanY;
  gLastPanX = evt.deltaX;
  gLastPanY = evt.deltaY;
  gViewer.MoveModel(deltaX, deltaY);
}

function OnPinchStart(evt) {
  if (evt.pointerType == 'mouse') { return; }
  gLastScale = 1;
}

function OnPinch(evt) {
  if (evt.pointerType == 'mouse') { return; }
  const scale = evt.scale / gLastScale;
  gLastScale = evt.scale;
  gViewer.ScaleModel(scale);
}

function OnCastViewportResize() {
  gViewer.Resize(gViewport.clientWidth, gViewport.clientHeight);
}

export default { attachEvents };
